package main

import "fmt"

func main() {
	arr := []int{8, 2, -9, 23, 92, 87}
	c := make(chan int)
	go sum(arr[:len(arr)/2], c)
	go sum(arr[len(arr)/2:], c)
	x, y := <-c, <-c //从通道c中获取值
	println(x, y, x+y)

	//通道缓冲区,设置大小为2
	ch := make(chan int, 2)

	// 因为 ch 是带缓冲的通道，我们可以同时发送两个数据
	// 而不用立刻需要去同步读取数据
	ch <- 1
	ch <- 2

	//获取缓冲区数据
	fmt.Println(<-ch, <-ch)

	c0 := make(chan int, 10) //定义缓冲量为10的通道
	go fibonacci(cap(c0), c0)
	// range 函数遍历每个从通道接收到的数据，因为 c 在发送完 10 个
	// 数据之后就关闭了通道，所以这里我们 range 函数在接收到 10 个数据
	// 之后就结束了。如果上面的 c 通道不关闭，那么 range 函数就不
	// 会结束，从而在接收第 11 个数据的时候就阻塞了。
	for i := range c0 {
		fmt.Println(i)
	}

	deadlock_01()
	deadlock_03()
}

/**
 * 求和传入 通道
 */
func sum(arr []int, c chan int) {
	sum := 0
	for _, value := range arr {
		sum += value
	}
	c <- sum //将和传到通道
}

/**
 * 斐波拉契数列
 */
func fibonacci(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	close(c) // 关闭通道
}

/**
 * 信道常见的示例1 死锁
 */
func deadlock_01() {
	pipeline := make(chan string) // 无缓冲信道 会出现阻塞
	// 解决死锁的方式1
	//pipeline := make(chan string, 1)
	// 解决死锁方式2 不同携程中接收
	go hello(pipeline)
	// 下面两行更换位置仍然死锁，主要是在同一个协程且无缓冲
	pipeline <- "hello world"
	//fmt.Println(<-pipeline)
}

func hello(pipeline chan string) {
	fmt.Println(<-pipeline)
}

//信道容量满了仍然发送数据导致死锁
func deadlock_02() {
	ch1 := make(chan string, 1)
	ch1 <- "hello world"
	ch1 <- "golang"
	fmt.Println(<-ch1)
}

// 信道不关闭造成死锁
func deadlock_03() {
	pipline := make(chan string)
	go func() {
		pipline <- "hello world"
		pipline <- "hello China"
		close(pipline)
	}()
	for data := range pipline {
		fmt.Println(data)
	}
}
